package mv.releaser.model;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;
import java.util.Observable;

public class MvReleaser extends Observable {

	private String				releaseName;
	private String				lastOpenPath;
	private String				lastSavePath;
	private Calendar			releaseDate;
	private int					minutes;
	private int					seconds;
	private int					width;
	private int					height;
	private String				artist;
	private String				audio;
	private String				filePath;
	private String				title;
	private String				genre;
	private String				type;
	private String				source;
	private String				deinterlace;
	private String				year;
	private AviInputFile		aviFile;
	private File				fin;
	private String				nfoPath;
	private String				crcCode;
	private String				comments;
	private String				lang;
	private String				format;
	private File				dout;
	private String				outputDirectory;
	private String				fps;
	private String				group;
	private String				ripper;

	private boolean	hdtv;
	private boolean	dvdrip;
	private boolean	readnfo;
	private boolean	dirfix;
	private boolean	proper;
	private boolean	repack;
	private boolean	nfoFix;

	public final static String	VERSION	= "1.0 beta1";

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#makeRelease()
	 */
	public void makeRelease(File dout) throws IOException, MoveAviFileException {
		if (fin == null)
			return;

		if (dout == null)
			return;

		if (crcCode == null || crcCode.equals(""))
			crcCode = Long.toHexString(new CRC(fin).getCRC());

		this.dout = dout;
		this.outputDirectory = dout.getAbsolutePath() + File.separator
				+ getReleaseName();

		makeDirectory();
		makeSFV();
		PrintStream nfoPS = new PrintStream(getOutputDirectory()
				+ getNfoFilename());
		makeNFO(nfoPS);
		moveAviFile();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setAviFile(java.io.File)
	 */
	public void setAviFile(File fin) throws IOException, NotAnAviFileException {
		// reset();
		aviFile = new AviInputFile(fin);
		this.fin = fin;

		minutes = aviFile.getMinutes();
		seconds = aviFile.getSeconds();
		width = aviFile.getWidth();
		height = aviFile.getHeight();
		fps = String.format(Locale.US, "%.3f", aviFile.getFrameRate());
		crcCode = "";

		setChanged();
		notifyObservers();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getCRC()
	 */
	public String getCRC() {
		return crcCode;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getMinutes()
	 */
	public String getMinutes() {
		if (minutes < 10)
			return "0" + minutes;
		else
			return "" + minutes;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getSeconds()
	 */
	public String getSeconds() {
		if (seconds < 10)
			return "0" + seconds;
		else
			return "" + seconds;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getWidth()
	 */
	public int getWidth() {
		return width;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getFPS()
	 */
	public String getFPS() {
		return fps;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getHeight()
	 */
	public int getHeight() {
		return height;
	}

	protected void makeDirectory() {
		new File(outputDirectory).mkdir();
	}

	protected void makeNFO(PrintStream nfoPS) throws IOException {
		String s_nfo = getNFOString();

		PrintWriter nfoPW = new PrintWriter(nfoPS);
		nfoPW.write(s_nfo);

		nfoPW.close();
		nfoPS.close();
	}

	protected void makeSFV() throws IOException {
		FileWriter sfv = new FileWriter(getOutputDirectory() + getSfvFilename());
		sfv.write(getAviFilename() + " " + getCRC());
		sfv.close();
	}

	protected void moveAviFile() throws IOException, MoveAviFileException {
		if (getAviFilename() == null)
			return;

		File destination = new File(getOutputDirectory() + getAviFilename());
		// System.out.println("Writable : " + fin.canWrite() + " - Destination :
		// " + destination.getAbsolutePath());
		// if move failed, throw an exception
		if (!fin.renameTo(destination)) {
			throw new MoveAviFileException("Unable to move "
					+ getOutputDirectory() + getAviFilename());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setArtist(java.lang.String)
	 */
	public void setArtist(String artist) {
		this.artist = artist;
		this.artist = StringUtilities.capitalize(this.artist);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setCrc(java.lang.String)
	 */
	public void setCrc(String crc) {
		this.crcCode = crc;
		setChanged();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setDeinterlace(java.lang.String)
	 */
	public void setDeinterlace(String deinterlace) {
		this.deinterlace = deinterlace;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setGenre(java.lang.String)
	 */
	public void setGenre(String genre) {
		this.genre = genre;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setHeight(java.lang.String)
	 */
	public void setHeight(int height) {
		this.height = height;
		setChanged();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setMinutes(java.lang.String)
	 */
	public void setMinutes(int minutes) {
		this.minutes = minutes;
		setChanged();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setReleaseDate(java.util.Calendar)
	 */
	public void setReleaseDate(Calendar releaseDate) {
		this.releaseDate = releaseDate;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setReleaseName(java.lang.String)
	 */
	public void setReleaseName(String releaseName) {
		this.releaseName = releaseName;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setSeconds(java.lang.String)
	 */
	public void setSeconds(int seconds) {
		this.seconds = seconds;
		setChanged();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setSource(java.lang.String)
	 */
	public void setSource(String source) {
		this.source = source;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setTitle(java.lang.String)
	 */
	public void setTitle(String title) {
		this.title = title;
		this.title = StringUtilities.capitalize(this.title);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setType(java.lang.String)
	 */
	public void setType(String type) {
		this.type = type;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setWidth(java.lang.String)
	 */
	public void setWidth(int width) {
		this.width = width;
		setChanged();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setYear(java.lang.String)
	 */
	public void setYear(String year) {
		this.year = year;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getFilePath()
	 */

	public String getFilePath() {
		if (fin == null)
			return "";
		return fin.getAbsolutePath();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setAudio(java.lang.String)
	 */

	public void setAudio(String audio) {
		this.audio = audio;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setLang(java.lang.String)
	 */

	public void setLang(String lang) {
		this.lang = lang;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#setFormat(java.lang.String)
	 */

	public void setFormat(String format) {
		this.format = format;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getArtist()
	 */
	public String getArtist() {
		if (artist == null)
			return "";
		return artist;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getAudio()
	 */
	public String getAudio() {
		if (audio == null)
			return "";
		return audio;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getAviFile()
	 */
	public AviInputFile getAviFile() {
		return aviFile;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getDeinterlace()
	 */
	public String getDeinterlace() {
		if (deinterlace == null)
			return "";
		return deinterlace;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getFormat()
	 */
	public String getFormat() {
		if (format == null)
			return "";
		return format;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getGenre()
	 */
	public String getGenre() {
		if (genre == null)
			return "";
		return genre;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getLang()
	 */
	public String getLang() {
		if (lang == null)
			return "";
		return lang;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getReleaseDate()
	 */
	public String getReleaseDate() {
		int day = releaseDate.get(Calendar.DAY_OF_MONTH);
		int month = releaseDate.get(Calendar.MONTH) + 1;
		int year = releaseDate.get(Calendar.YEAR);

		String sDay = day < 10 ? "0" + day : "" + day;
		String sMonth = month < 10 ? "0" + month : "" + month;

		return sDay + "/" + sMonth + "/" + year;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getReleaseName()
	 */
	public String getReleaseName() {
		if (releaseName == null)
			return "";
		return releaseName;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getSource()
	 */
	public String getSource() {
		if (source == null)
			return "";
		return source;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getTitle()
	 */
	public String getTitle() {
		if (title == null)
			return "";
		return title;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getType()
	 */
	public String getType() {
		if (type == null)
			return "";
		return type;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see mv.releaser.model.test#getYear()
	 */
	public String getYear() {
		if (year == null)
			return "";
		return year;
	}

	public String getLastOpenPath() {
		return lastOpenPath;
	}

	public void setLastOpenPath(String lastOpenPath) {
		this.lastOpenPath = lastOpenPath;
	}

	public String getLastSavePath() {
		return lastSavePath;
	}

	public void setLastSavePath(String lastSavePath) {
		this.lastSavePath = lastSavePath;
	}

	public String getAviFilename() {
		if (getReleaseName() == null)
			return null;

		return getReleaseName().toLowerCase() + ".avi";
	}

	public String getOutputDirectory() {
		return outputDirectory + File.separator;
	}

	public String getSfvFilename() {
		if (getReleaseName() == null)
			return null;

		return getReleaseName().toLowerCase() + ".sfv";
	}

	public String getNfoFilename() {
		if (getReleaseName() == null)
			return null;

		return getReleaseName().toLowerCase() + ".nfo";
	}

	public String previewNFO() throws IOException {
		String nfo = getNFOString();
		return nfo;
	}

	private String getNFOString() throws IOException {
		InputStream nfoIS;
		if (nfoPath == null)
			nfoIS = getClass().getResourceAsStream(
					"/mv/releaser/resources/skel.nfo");
		else
			nfoIS = new FileInputStream(nfoPath);
		InputStreamReader nfoISR = new InputStreamReader(nfoIS, "ISO-8859-1");

		NFO nfo = new NFO(this, nfoISR);
		String s_nfo = nfo.fillNFO();

		return s_nfo;
	}

	public String getSize() {
		if (fin == null)
			return "";
		return "" + fin.length();
	}

	public String getComments() {
		return comments;
	}

	public String getLength() {
		return getMinutes() + ":" + getSeconds();
	}

	public String getResolution() {
		return getWidth() + "x" + getHeight();
	}

	public void reset() {
		minutes = 0;
		seconds = 0;
		width = 0;
		height = 0;
		filePath = null;
		aviFile = null;
		setChanged();
		notifyObservers();
	}

	public boolean copyAviFile() {
		if (fin == null)
			return false;

		if (getAviFilename() == null)
			return false;

		File destination = new File(getOutputDirectory() + getAviFilename());
		boolean success = true;
		InputStream in;
		OutputStream out;

		try {
			in = new FileInputStream(fin);
			out = new FileOutputStream(destination);

			// Transfer bytes from in to out
			byte[] buf = new byte[1024];
			int len;
			while ((len = in.read(buf)) > 0) {
				out.write(buf, 0, len);
			}
			in.close();
			out.close();
		} catch (FileNotFoundException e) {
			success = false;
			e.printStackTrace();
		} catch (IOException e) {
			success = false;
			e.printStackTrace();
		}

		return success;
	}

	public void setNfoTemplate(String nfoPath) {
		this.nfoPath = nfoPath;
	}

	public void setComments(String comments) {
		this.comments = comments;
	}

	public void setFps(String fps) {
		this.fps = fps;
		setChanged();
	}

	public void setGroup(String group) {
		this.group = group;
	}

	public void setRipper(String ripper) {
		this.ripper = ripper;
	}

	public String getRipper() {
		if (ripper == null)
			return "";
		return ripper;
	}

	public boolean isDirfix() {
		return dirfix;
	}

	public void setDirfix(boolean dirfix) {
		this.dirfix = dirfix;
	}

	public boolean isDvdrip() {
		return dvdrip;
	}

	public void setDvdrip(boolean dvdrip) {
		this.dvdrip = dvdrip;
	}

	public boolean isHdtv() {
		return hdtv;
	}

	public void setHdtv(boolean hdtv) {
		this.hdtv = hdtv;
	}

	public boolean isProper() {
		return proper;
	}

	public void setProper(boolean proper) {
		this.proper = proper;
	}

	public boolean isReadnfo() {
		return readnfo;
	}

	public void setReadnfo(boolean readnfo) {
		this.readnfo = readnfo;
	}

	public boolean isRepack() {
		return repack;
	}

	public void setRepack(boolean repack) {
		this.repack = repack;
	}

	public boolean isNfoFix() {
		return nfoFix;
	}

	public void setNfoFix(boolean nfoFix) {
		this.nfoFix = nfoFix;
	}


}
